<script>
    // vue2.x的响应式原理
    function updateView() {
        console.log("视图更新了~");
    }

    // 把Array的原型对象，赋值给oldArrayProperty
    let oldArrayProperty = Array.prototype;
    let arrProto = Object.create(oldArrayProperty);
    ["push", "pop", "shift", "unshift", "splice"].forEach(methodName => {
        // console.log(methodName);
        // 调用这7个方法时，调用的并不是原生的push是我们自己重写后的push
        arrProto[methodName] = function () {
            updateView(); // 更新视图
            oldArrayProperty[methodName].call(this, ...arguments)
        }
    })

    function definedReactive(target, key, value) {
        // console.log(target,key,value);
        observer(value); // 深度监听

        Object.defineProperty(target, key, {
            get() {
                // console.log("get...");
                return value
            },
            set(newValue) {
                observer(newValue); // 深度监听

                value = newValue
                // 数据变了，我监听到了，我要去更新视图
                updateView()
            }
        })
    }

    function observer(target) {
        if (typeof target !== "object" || target === null) {
            return target
        }

        if (Array.isArray(target)) {
            // console.log(target+"是数组");
            // 如果是数组，改变原型对象
            target.__proto__ = arrProto;
        }

        for (let key in target) {
            definedReactive(target, key, target[key])
        }
    }

    // 准备数据
    // 目的：name,age,info,address
    let data = {
        name: "码路",
        age: 18,
        info: {
            address: "bj",
        },
        arr: ["ml", "wc", "xq"]
    };

    // data.arr.push("z3")  当调用push时，模板也需要重新渲染
    // 在vue2.x中重写了数组的7个方法，在7个方法中更新了视图

    // 监听数据，数据劫持
    observer(data)

    // 当数据变了，要更新视图
    // console.log(data.name);
    // data.name = "malu";
    // console.log(data.name);
</script>